package cn.chenxinjie.hrm.config;

import cn.chenxinjie.hrm.authenhandle.MyAuthenFail;
import cn.chenxinjie.hrm.authenhandle.MyAuthenSuccess;
import cn.chenxinjie.hrm.filter.SmsCodeFilter;
import cn.chenxinjie.hrm.mapper.PermissionMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * @author 陈鑫杰
 * @date 2022/3/19 11:01
 */
@EnableWebSecurity // 开启Web安全配置
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法注解授权
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private SmsCodeConfig smsCodeConfig;

    /**
     * Http安全配置
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login", "/login.html", "/smslogin").permitAll() // 放行登陆请求
                .antMatchers(HttpMethod.POST,"/sms/send/**").permitAll()
                .anyRequest().authenticated() // 其他请求都需要认证
                .and().formLogin() // 允许表单登陆
                //.successForwardUrl("/success") // 登陆成功后转发
                .successHandler(new MyAuthenSuccess())
                .failureHandler(new MyAuthenFail())
                .loginPage("/login.html").loginProcessingUrl("/login")
                .and().logout().permitAll() // 放行退出请求
                .and().csrf().disable();// 关闭跨站伪造检查
        http.rememberMe().tokenRepository(createTokenRepository())
                .tokenValiditySeconds(3600)
                .userDetailsService(userDetailsService);
        // 将短信验证码校验的过滤器添加到UsernamePasswordAuthenticationFilter过滤器之前
        SmsCodeFilter smsCodeFilter = new SmsCodeFilter();
        http.addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class);
        // 应用单独配置
        http.apply(smsCodeConfig);
    }
    // web授权
    /*@Override
    protected void configure(HttpSecurity http) throws Exception {

        List<Permission> permissions = permissionMapper.selectList(null);
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.authorizeRequests();

        permissions.stream().forEach(permission -> {
            registry.antMatchers(permission.getResource()).hasAuthority(permission.getSn());
        });

        registry.antMatchers("/login", "/login.html").permitAll() // 放行登陆请求
                .anyRequest().authenticated() // 其他请求都需要认证
                .and().formLogin() // 允许表单登陆
                //.successForwardUrl("/success") // 登陆成功后转发
                .successHandler(new MyAuthenSuccess())
                .failureHandler(new MyAuthenFail())
                .loginPage("/login.html").loginProcessingUrl("/login")
                .and().logout().permitAll() // 放行退出请求
                .and().csrf().disable();// 关闭跨站伪造检查

    }*/


    // 内存中模拟
    /*@Override
    @Bean
    protected UserDetailsService userDetailsService() {
        User user = new User("chenxinjie", "1", new ArrayList<>());
        UserDetailsService manager = new InMemoryUserDetailsManager(user);
        return manager;
    }*/


    // 告知security无需加密解析方式
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 使用BCrypt加密方式
        return new BCryptPasswordEncoder();
        //return NoOpPasswordEncoder.getInstance();
    }

    @Autowired
    private DataSource dataSource;

    /**
     * 指明token的持久化方案,配置remember-me
     *
     * @return
     */
    @Bean
    public PersistentTokenRepository createTokenRepository(){
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        tokenRepository.setCreateTableOnStartup(false);
        return tokenRepository;
    }

    /**
     * 测试BCrypt加密
     * @param args
     */
    public static void main(String[] args) {
        String pwd = "1";
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String encode = encoder.encode(pwd);
        System.out.println(encode);
    }
}
